package org.test4j.mock.startup;

import org.test4j.mock.faking.FakeInvoker;
import org.test4j.mock.faking.modifier.BridgeTransformer;
import org.test4j.mock.faking.modifier.FakeTransformer;
import org.test4j.mock.faking.util.ClassLoad;

import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;

/**
 * This is the "agent class" that initializes the MockFrame "Java agent",
 *
 * @see #premain(String, Instrumentation)
 */
public final class Startup {
    public static boolean initializing;

    private static Instrumentation instrumentation;

    private Startup() {
    }

    public static void premain(String agentArgs, Instrumentation inst) {
        instrumentation = inst;
        instrumentation.addTransformer(new BridgeTransformer());
        FakeInvoker.getHostClassName();
        // Loads some JRE classes expected to not be loaded yet.
        ClassLoad.loadClass(FakeInvoker.getHostClassName());
        instrumentation.addTransformer(FakeTransformer.INSTANCE, true);
        initializing = true;
        try {
            JavaAgentHits.message();
            MockInitialization.initialize();
        } finally {
            initializing = false;
        }
    }

    public static void verifyInitialization() {
        if (instrumentation == null) {
            throw new IllegalStateException(JavaAgentHits.message());
        }
    }

    public static void reTransformClass(Class aClass) {
        try {
            instrumentation.retransformClasses(aClass);
        } catch (UnmodifiableClassException ignore) {
        } catch (Throwable e) {
            throw new RuntimeException("reTransformClass:" + aClass.getName() + " error", e);
        }
    }
}